﻿using System;

namespace Kyoh
{
	public class ComplexInfo<T> : IFormatProvider, ICustomFormatter
		where T:IComparable<T>
	{
		public ComplexInfo()
		{
			RealNumberFormat =
			ImaginaryNumberFormat = null;
			ImaginaryNumberProvider =
			RealNumberProvider = System.Globalization.NumberFormatInfo.CurrentInfo;
		}
		public string RealNumberFormat { get; set; }
		public string ImaginaryNumberFormat { get; set; }
		public IFormatProvider RealNumberProvider { get; set; }
		public IFormatProvider ImaginaryNumberProvider { get; set; }

		#region ICustomFormatter メンバ

		private static string _NumberFormat(IFormatProvider provider, string format, T arg)
		{
			if (format != null)
				return string.Format(provider, "{0:" + format + "}", arg);
			else if (provider != null)
				return string.Format(provider, "{0:" + format + "}", arg);
			else
				return arg.ToString();
		}

		public string Format(string format, object arg, IFormatProvider formatProvider)
		{
			if (arg is Complex<T>)
			{
				Complex<T> z = (Complex<T>)arg;
				switch (format)
				{
					case "j":
						return
							_NumberFormat(RealNumberProvider, RealNumberFormat ?? "g", z.Real) +
							(Operator<T>.IsNegative(z.Imginary) ? "-" : "+") +
							"j" +
							_NumberFormat(ImaginaryNumberProvider, ImaginaryNumberFormat ?? "g", Operator<T>.Absolute(z.Imginary));

					case "J":
						return
							_NumberFormat(RealNumberProvider, RealNumberFormat ?? "G", z.Real) +
							(Operator<T>.IsNegative(z.Imginary) ? "-" : "+") +
							"J" +
							_NumberFormat(ImaginaryNumberProvider, ImaginaryNumberFormat ?? "G", Operator<T>.Absolute(z.Imginary));

					case "":
					case null:
					case "i":
						return
							_NumberFormat(RealNumberProvider, RealNumberFormat ?? "g", z.Real) +
							(Operator<T>.IsNegative(z.Imginary) ? "-" : "+") +
							_NumberFormat(ImaginaryNumberProvider, ImaginaryNumberFormat ?? "g", Operator<T>.Absolute(z.Imginary)) +
							"i";

					case "I":
						return
							_NumberFormat(RealNumberProvider, RealNumberFormat ?? "G", z.Real) +
							(Operator<T>.IsNegative(z.Imginary) ? "-" : "+") +
							_NumberFormat(ImaginaryNumberProvider, ImaginaryNumberFormat ?? "G", Operator<T>.Absolute(z.Imginary)) +
							"I";

					default:
						return "";
				}
			}
			else if (arg != null)
				return arg.ToString();
			else
				return "";
		}

		#endregion

		#region IFormatProvider メンバ

		public object GetFormat(Type formatType)
		{
			if (formatType == typeof(ComplexInfo<T>))
				return this;
			else
				return null;
		}

		#endregion
	}
}
